/*
 * This file is part of PDBEdit.
 * 
 * PDBEdit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * PDBEdit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PDBEdit.  If not, see <http://www.gnu.org/licenses/>.
 *  
 * Creation date : 13/05/2011
 * Copyright (c) Guerfyld 2010. All rights reserved.
 * http://......
 */
package pdbfile;

import java.io.DataInputStream;
import java.io.InputStream;

/**
 * The PDBInputStream class manage a input stream of datas
 *
 * @author guerfyld
 * @version 1.0
 */
public class PDBInputStream extends DataInputStream {
	private byte[] content;
	private long offset;

	// Constantes
	public static final int BUFFERSIZE = 128;
	public static final int MAXLENGTH = 128;

	/**
	 * Constructor
	 *
	 * @param is	Stream to read
	 */
	public PDBInputStream(InputStream is) {
		super(is);
		content = null;
		offset = 0;
	}

	/**
	 * Read a byte
	 *
	 * @param i	Byte position
	 * @return	Read byte
	 */
	public byte readByte(long i) throws Exception {
		try {
			if (content == null) {
				content = new byte[BUFFERSIZE];
				read(content);
				offset = 0;
			}
			if (i>=offset+BUFFERSIZE) {
				int len = read(content);
				offset += BUFFERSIZE;
			}

			return content[(int)(i - offset)];
		}
		catch(Exception e) {
			e.printStackTrace();
			throw new Exception("PDBInputStream.readByte : "+e.getMessage()+" reading byte "+i+" (offset="+offset+")");
		}
	}

	/**
	 * Read a numeric value
	 *
	 * @param start		Start byte position
	 * @param size		Number of byte to read (1, 2, 4, 8)
	 * @return		Read value
	 */
	public long readValue(long start, int size) throws Exception {
		long res = 0;
		
		//System.out.print(start+" :");
		for (int i=0; i<size; i++) {
			//System.out.print(" "+getHex(readByte(start+i)));
			res = (res << 8) + (readByte(start+i) & 0xFF);
		}
		//System.out.println("("+res+")");
		
		return res;
	}

	/**
	 * Read a string value
	 *
	 * @param start		Start byte position
	 * @param size		Number of byte to read
	 * @return		Read string
	 */
	public String readString(long start, int size) throws Exception {
		byte[] strBuffer = new byte[size];
			
		//System.out.print(start+" : ");
		for (int i=0; i<size; i++) {
			strBuffer[i] = readByte(start+i);
		}

		String res = new String(strBuffer, 0, size);
		//System.out.println(res);		
		return res;
	}

	/**
	 * Read a stringZ value
	 *
	 * @param start		Start byte position
	 * @return		Read string
	 */
	public String readStringZ(long start) throws Exception {
		byte[] strBuffer = new byte[MAXLENGTH];
		int size = 0;
		
		//System.out.print(start+" : ");
		for (int i=0; i<MAXLENGTH; i++) {
			strBuffer[i] = readByte(start+i);
			if (strBuffer[i] == 0) break;
			size++;
		}
		
		String res = new String(strBuffer, 0, size);
		//System.out.println(res);		
		return res;
	}
	
	// Convert to hexa (For debugging)
	private final static String hexcar = "0123456789ABCDEF";
	private static String getHex(byte b) {
		String res = "";
		short j;

		j = b < 0 ? (short) (256 + b) : b;
		j = (short) (j >>> 4);
		res += hexcar.charAt(j);
		j = (short) (b & 15);
		res += hexcar.charAt(j);
        
		return res;
	}
}